#include "user_global.h"
#include "modbus.h"
#include "user_device.h"
#include "iwdg.h"

#define RESERVED_SPACE_ADDR         0x7E00

// 读取异常状态
uchar Read_Exception(void)
{
    return program_status;
}

void Enter_Boot_Loader(void)
{
    MX_IWDG_Init();
}

void Restart(void)
{
    NVIC_SystemReset();
}

// 诊断
void Diagnose(void)
{
    ushort subfun = from_little_endian_16(*(ushort*)&uart0_buf[2]);    // 子功能代码

    switch(subfun)
    {
    case 0x00:        // 原样返回请求数据
    case 0x03:        // 改变ASCII结束符
        uart0_len -= 2;
        Response();
        break;

    case 0x01:        // 复位通讯端口
        uart0_len = 6;
        subfun = from_little_endian_16(*(ushort*)&uart0_buf[4]);
        Response();

        // 等等发送结束
        while(uart0_tx_pending)
            Update_WatchDog();
        if (subfun == 0xFF00)    // 清除记录事件
            event_count = 0;

        // 等等停止位发送结束
        Delay_us(100);

        // 重启
        if (subfun == 0xFFFF)
            Enter_Boot_Loader();
        else
            Restart();

        break;            // 运行不到此处

    case 0x02:        // 返回诊断寄存器
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(diagnostic);
        Response();
        break;

    case 0x04:      // 强迫进入“只听”模式
        ps_listen_only = 1;
        No_Response();
        Log_Event(EVENT_ENTER_LISTEN_ONLY);
        break;

    case 0x0A:        // 清除计数器和诊断寄存器
        diagnostic                      = 0;        // 诊断寄存器
        bus_message_count               = 0;        // 总线上消息数量
        bus_error_count                 = 0;        // 总线上通讯错误数量
        bus_exception_count             = 0;        // 总线上异常应答数量
        server_message_count            = 0;        // 下位机消息数量
        server_no_response_count        = 0;        // 下位机未响应消息数量
        server_exception_count          = 0;        // 下位机异常应答消息数量
        server_busy_count               = 0;        // 下位机状态忙数量
        bus_char_overrun_count          = 0;        // 总线字符过载（Overrun）数量

        uart0_len -= 2;
        Response();
        break;

    case 0x0B:        // 返回总线上消息数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(bus_message_count);
        Response();
        break;

    case 0x0C:        // 返回总线上通讯错误数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(bus_error_count);
        Response();
        break;

    case 0x0D:        // 返回总线上异常应答数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(bus_exception_count);
        Response();
        break;

    case 0x0E:        // 返回下位机消息数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(server_message_count);
        Response();
        break;

    case 0x0F:        // 返回下位机未响应消息数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(server_no_response_count);
        Response();
        break;

    case 0x10:        // 返回下位机异常应答消息数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(server_exception_count);
        Response();
        break;

    case 0x11:        // 返回下位机状态忙数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(server_busy_count);
        Response();
        break;

    case 0x12:        // 返回总线字符过载（Overrun）数量
        uart0_len = 6;
        *(ushort*)&uart0_buf[4] = from_little_endian_16(bus_char_overrun_count);
        Response();
        break;

    case 0x14:        // 清除过载（Overrun）计数器和标志
        uart0_len -= 2;
        bus_char_overrun_count = 0;
        Response();
        break;

    default:        // 未实现或不正确的子功能代码
        Exception_Response(ILLEGAL_FUNCTION);
        break;
    }
}

void Log_Event(uchar event)
{
    event_log[++event_count & MAX_EVENT_MASK] = event;
    if (event_count > MAX_EVENT_MASK)
        event_count = (event_count & MAX_EVENT_MASK) | MAX_EVENT_COUNT;
}
